package com.hy.service.impl;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hy.common.base.RespResult;
import com.hy.common.base.RespResultCode;
import com.hy.common.consts.CommonConst;
import com.hy.common.excel.HyPropertyPlaceImport;
import com.hy.common.excel.HyPropertySortImport;
import com.hy.common.exception.ImportException;
import com.hy.common.utils.CommonUtils;
import com.hy.common.utils.ExcelUtil;
import com.hy.entity.dto.ProperSortDTO;
import com.hy.entity.pojo.HyPlace;
import com.hy.entity.pojo.HyPropertySort;
import com.hy.entity.pojo.UserRoleConn;
import com.hy.entity.vo.*;
import com.hy.mapper.HyPropertySortMapper;
import com.hy.mapper.HyUnitMapper;
import com.hy.service.HyPropertySortService;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;
import java.util.*;

@Slf4j
@Service
public class HyPropertySortServiceImpl implements HyPropertySortService {

    @Resource
    private HyPropertySortMapper hyPropertySortMapper;
    @Resource
    private HyUnitMapper unitMapper;

    @Resource
    private SqlSessionFactory sqlSessionFactory;
    private Authentication authentication;
    @Override
    public RespResult addPropertySort(HyPropertySort sort) {
        sort.setDel(1);
        authentication= SecurityContextHolder.getContext().getAuthentication();
        HyUserVO principal = (HyUserVO) authentication.getPrincipal();
        List<String> roles = principal.getRoles();
        sort.setCreateDate(CommonUtils.getDate());
        RespResult result;
        if (CommonUtils.isMember(roles, CommonConst.SYSTEM_ROLE_NAME)){
            hyPropertySortMapper.insert(sort);
            result=RespResult.success();
        }else {
           sort.setUnitId(principal.getUnitId());
            hyPropertySortMapper.insert(sort);
            result=RespResult.success();
        }
        return result;
    }

    public boolean isCheck(List<Integer> placeIds){
        authentication= SecurityContextHolder.getContext().getAuthentication();
        HyUserVO currentUserInfo=(HyUserVO)authentication.getPrincipal();
        for (Integer placeId:placeIds) {
            HyPropertySort hySort = hyPropertySortMapper.selectById(placeId);
            if (!hySort.getUnitId().equals(currentUserInfo.getUnitId())){
                return false;
            }
        }
        return true;

    };
    @Override
    public RespResult updatePropertySort(HyPropertySort sort) {

        authentication= SecurityContextHolder.getContext().getAuthentication();
        HyUserVO principal = (HyUserVO) authentication.getPrincipal();
        List<String> roles = principal.getRoles();
        RespResult result;
        if (CommonUtils.isMember(roles, CommonConst.SYSTEM_ROLE_NAME)){
            hyPropertySortMapper.updateById(sort);
            result=RespResult.success();
        }else {
            if (isCheck(new ArrayList<>(sort.getSortId()))){
                sort.setUnitId(principal.getUnitId());
                hyPropertySortMapper.insert(sort);
                result=RespResult.success();
            }else {
                result=RespResult.getInstance(RespResultCode.NO_AUTH);
            }

        }
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public RespResult deletePropertySort(List<Integer> ids) {
        authentication= SecurityContextHolder.getContext().getAuthentication();
        HyUserVO principal = (HyUserVO) authentication.getPrincipal();
        List<String> roles = principal.getRoles();
        RespResult result;
        if (CommonUtils.isMember(roles, CommonConst.SYSTEM_ROLE_NAME)){
            hyPropertySortMapper.deleteBatchIds(ids);
            result=RespResult.getInstance(RespResultCode.DEL_SUCCESS);
        }else {
            if (isCheck(ids)){

               hyPropertySortMapper.deleteBatchIds(ids);
                result=RespResult.getInstance(RespResultCode.DEL_SUCCESS);
            }else {
                result=RespResult.getInstance(RespResultCode.NO_AUTH);
            }

        }
        return result;
    }

    @Override
    public RespResult showPropertySortByDto(ProperSortDTO sortDTO) {
        sortDTO.setDel(1);
        authentication= SecurityContextHolder.getContext().getAuthentication();
        HyUserVO principal = (HyUserVO) authentication.getPrincipal();
        List<String> roles = principal.getRoles();
        RespResult result;
        if (CommonUtils.isMember(roles, CommonConst.SYSTEM_ROLE_NAME)){
            List<HyPropertySortVO> hyPropertySortVOS = hyPropertySortMapper.showPropertySortByDto(null, sortDTO);
            List<HyPropertySortVO> hyPropertySortVOS1 = showSortVO(hyPropertySortVOS);
            result=RespResult.success(hyPropertySortVOS1);
        }else {
            sortDTO.setUnitId(principal.getUnitId());
            List<HyPropertySortVO> hyPropertySortVOS = hyPropertySortMapper.showPropertySortByDto(null, sortDTO);
            List<HyPropertySortVO> hyPropertySortVOS1 = showSortVO(hyPropertySortVOS);
            result=RespResult.success(hyPropertySortVOS1);
        }
        return result;
    }
    public List<HyPropertySortVO> showSortVO(List<HyPropertySortVO> sort){
        authentication= SecurityContextHolder.getContext().getAuthentication();
        HyUserVO principal = (HyUserVO) authentication.getPrincipal();

        Iterator<HyPropertySortVO> iterator;

        List<HyPropertySortVO> sortTreeVOS=new ArrayList<>();
        iterator = sort.iterator();

        while (iterator.hasNext()){
            HyPropertySortVO theNext = iterator.next();
            if (theNext.getSortMgr().equals(10000)){
                HyPropertySortVO hyPlaceVO=new HyPropertySortVO();
                BeanUtils.copyProperties(theNext,hyPlaceVO);
                sortTreeVOS.add(hyPlaceVO);
                iterator.remove();
            }
        }
        getSortTrees(sort,sortTreeVOS);
        return sortTreeVOS;
    }

    private List<HyPropertySortVO> getSortTrees(List<HyPropertySortVO> sort, List<HyPropertySortVO> sortTreeVOS) {

        for (int i = 0; i < sortTreeVOS.size(); i++) {
            HyPropertySortVO tree = sortTreeVOS.get(i);
            Integer id = tree.getSortId();
            List<HyPropertySortVO> child=new ArrayList<>();
            Iterator<HyPropertySortVO> leftIt = sort.iterator();
            while (leftIt.hasNext()){
                HyPropertySortVO next = leftIt.next();
                if (id.equals(next.getSortMgr())){
                    HyPropertySortVO sortTreeVO=new HyPropertySortVO();
                    BeanUtils.copyProperties(next,sortTreeVO);
                    child.add(sortTreeVO);
                    leftIt.remove();
                }
            }
            tree.setChildren(child);
        }
        return sortTreeVOS;
    }

    @Override
    public RespResult showTreeSort() {
        authentication= SecurityContextHolder.getContext().getAuthentication();
        HyUserVO principal = (HyUserVO) authentication.getPrincipal();
        List<String> roles = principal.getRoles();
        RespResult result;
        if (CommonUtils.isMember(roles, CommonConst.SYSTEM_ROLE_NAME)){
            LambdaQueryWrapper<HyPropertySort> hyPropertySortLambdaQueryWrapper=new LambdaQueryWrapper<>();
            hyPropertySortLambdaQueryWrapper.eq(HyPropertySort::getUnitId,CommonConst.DEFAULT_ID).eq(HyPropertySort::getDel,1);
            result = getResult(hyPropertySortLambdaQueryWrapper);

        }else {
            LambdaQueryWrapper<HyPropertySort> hyPropertySortLambdaQueryWrapper=new LambdaQueryWrapper<>();
            hyPropertySortLambdaQueryWrapper.eq(HyPropertySort::getDel,1).in(HyPropertySort::getUnitId,CommonConst.DEFAULT_ID,principal.getUnitId());
            result = getResult(hyPropertySortLambdaQueryWrapper);
        }
        return result;


    }

    @Override
    public List<HyPropertySortVO> listPage(Map<String, Object> queryCondition, Integer pageNo, Integer pageSize) {
        Integer offset = (pageNo - 1) * pageSize;
        Integer rows = pageSize;
        authentication= SecurityContextHolder.getContext().getAuthentication();
        HyUserVO principal = (HyUserVO) authentication.getPrincipal();
        List<String> roles = principal.getRoles();
        queryCondition.put("offset",offset);
        queryCondition.put("rows",rows);
        List<HyPropertySortVO> propertySortVOS=null;
        if(CommonUtils.isMember(roles, CommonConst.SYSTEM_ROLE_NAME)){

            propertySortVOS= hyPropertySortMapper.findHyPropertyListByMap(queryCondition);
        }else {
            queryCondition.put("unitId",principal.getUnitId());
            propertySortVOS=hyPropertySortMapper.findHyPropertyListByMap(queryCondition);
        }
        return propertySortVOS;
    }

    @Override
    public void saveStuListWithBatch(List<HyPropertySort> data) {
        /**
         * mybatis提供三种sql执行器，分别是SIMPLE（默认）、REUSE、BATCH
         * SIMPLE	默认执行器， 节约服务器资源	每次都要开关Statement
         * REUSE	提升后端接口处理效率	每次一个新sql都缓存，增大JVM内存压力
         * BATCH	专门用于更新插入操作，效率最快	对select 不适用，另外特殊要求，比如限制一次execteBatch的数量时需要写过滤器定制
         */
        // 打开批处理
        SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
        /*HyPropertyBatchMapper empBatchMapper = session.getMapper(HyPropertyBatchMapper.class);*/
        for (int i = 0,length = data.size(); i < length; i++) {
            HyPropertySort propertySort = data.get(i);

            hyPropertySortMapper.insert(propertySort);
//            empBatchMapper.insert(data.get(i));
            //每1000条提交一次防止内存溢出
            if(i % 10000==9999){
                session.commit();
                session.clearCache();
            }
        }
        session.commit();
        session.clearCache();
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RespResult importExcelBigData(MultipartFile multipartFile, HttpServletRequest request) {
        RespResult r = RespResult.success();

        try{
            long start = System.currentTimeMillis();
            HyPropertySortImport excelImport=new HyPropertySortImport(this,unitMapper,hyPropertySortMapper);
            Integer sheetNo = Convert.toInt(request.getParameter("sheetNo"), 0);
            ExcelUtil.readExcel(multipartFile.getInputStream(), HyPropertySortReadVO.class,
                    excelImport, sheetNo);
            log.info("本次导入100w数据，总耗时:{}ms", (System.currentTimeMillis() -start));
            r.setCode(200);
            r.setMessage("导入成功");
            return r;
        } catch (Exception e){
            log.error(e.getMessage(), e);
            throw new ImportException(e.getMessage());
        }

    }
    private RespResult getResult(LambdaQueryWrapper<HyPropertySort> hyPropertySortLambdaQueryWrapper) {
        List<HyPropertySort> hyPropertySorts;
        List<SortTreeVO> sortTreeVOS;
        Iterator<HyPropertySort> iterator;
        RespResult result;
        hyPropertySorts= hyPropertySortMapper.selectList(hyPropertySortLambdaQueryWrapper);
        sortTreeVOS=new ArrayList<>();
        iterator = hyPropertySorts.iterator();

        while (iterator.hasNext()){
            HyPropertySort theNext = iterator.next();
            if (theNext.getSortMgr()==0){
                SortTreeVO sortTreeVO=new SortTreeVO();
                sortTreeVO.setOperation(theNext.getUnitId());
                sortTreeVO.setId(theNext.getSortId());
                sortTreeVO.setLabel(theNext.getSortName());
                sortTreeVOS.add(sortTreeVO);
                iterator.remove();
            }
        }
        SortTreeVO sortTreeVO=new SortTreeVO();
        sortTreeVO.setId(CommonConst.DEFAULT_ID);
        sortTreeVO.setLabel("暂无");
        sortTreeVO.setOperation(CommonConst.DEFAULT_ID);
        sortTreeVOS.add(sortTreeVO);
        List<SortTreeVO> sortTree = getSortTree(hyPropertySorts,sortTreeVOS);
        result=RespResult.success(sortTree);
        return result;
    }

    public List<SortTreeVO> getSortTree(List<HyPropertySort> sortVOS,List<SortTreeVO> sortTreeVOS){

        for (int i = 0; i < sortTreeVOS.size(); i++) {
            SortTreeVO tree = sortTreeVOS.get(i);
            Integer id = tree.getId();
            List<SortTreeVO> child=new ArrayList<>();
            Iterator<HyPropertySort> leftIt = sortVOS.iterator();
            while (leftIt.hasNext()){
                HyPropertySort next = leftIt.next();
                if (id.equals(next.getSortMgr())){
                    SortTreeVO sortTreeVO=new SortTreeVO();
                    sortTreeVO.setOperation(next.getUnitId());
                    sortTreeVO.setId(next.getSortId());
                    sortTreeVO.setLabel(next.getSortName());
                    child.add(sortTreeVO);
                    leftIt.remove();
                }
            }
            tree.setChildren(child);
        }
        return sortTreeVOS;
    }



}
